package com.example.emos.wx.config.shiro;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**先写jwt，再写shiro，jwt是用来可以单点登录的，shiro是用来认证和授权的。*/
/**先写jwt，再写shiro，jwt是用来可以单点登录的，shiro是用来认证和授权的。*/
/**先写jwt，再写shiro，jwt是用来可以单点登录的，shiro是用来认证和授权的。*/
/**先写jwt，再写shiro，jwt是用来可以单点登录的，shiro是用来认证和授权的。*/
/**先写jwt，再写shiro，jwt是用来可以单点登录的，shiro是用来认证和授权的。*/
/**
 * @ClassName : JwtUtil
 * @Author : 骆发茂
 * @Date: 2021/10/10 19:22
 * @Description :
 */


/**通过id获取token、验证token、token的生成、
jwt生成token，里面不要有敏感信息，或者对敏感信息单独加密，否则，会造成信息泄露*/

    /**JWT(单点登录) 的原理是，服务器认证以后，生成一个 JSON 对象，发回给用户。
     此后，用户与服务端通信的时候，都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。
     为了防止用户篡改数据，服务器在生成这个对象的时候，会加上签名。
     服务器就不保存任何 session 数据了，也就是说，服务器变成无状态了，从而比较容易实现扩展。*/
@Component
@Slf4j
public class JwtUtil_根据ID生成_解密获ID_验证TOKEN {
    /**是org.springframework.beans.factory中的value，注入数据*/
    @Value("${emos.jwt.secret}")
    private String secret;
        /**是org.springframework.beans.factory中的value，注入数据*/
        @Value("${emos.jwt.expire}")
    private int expire;

    /*通过传入的userid，创建、生成token，  createToken用于生成token，   需要三部分，userid，加密算法，过期时间*/
    public String createToken(int userId) {
        /**日期时间偏移
         日期或时间的偏移指针对某个日期增加或减少分、小时、天等等，达到日期变更的目的。
         String dateStr = "2017-03-01 22:33:23";
         Date date = DateUtil.parse(dateStr);
         //结果：2017-03-03 22:33:23
         Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);
         //常用偏移，结果：2017-03-04 22:33:23
         DateTime newDate2 = DateUtil.offsetDay(date, 3);
         //常用偏移，结果：2017-03-01 19:33:23
         DateTime newDate3 = DateUtil.offsetHour(date, -3);*/


        /**计算过期日期，定义过五天之后过期*/
        Date date = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, 5);
        /**使用了HMAC256加密算法。
         * secret是用来加密数字签名的密钥，secret是个密钥*/
        /*//密钥封装成加密算法，*/
        Algorithm algorithm = Algorithm.HMAC256(secret);

        /**JWT创建对象builder*/
        JWTCreator.Builder builder = JWT.create();//创建内部类对象
        String token = builder.withClaim("userId", userId).withExpiresAt(date).sign(algorithm);//绑定id，时间，算法
        return token;
    }


    /**
    /**解密，根据token获取id*/
        /**
         *
         * @param token
         * @return
         */
    public int getUserId(String token) {
        DecodedJWT jwt = JWT.decode(token);//解码
/**        从令牌字符串中反向获取id,
         为什么怎么知道是userId,不叫其他的？
         因为上面就绑定了builder.withClaim("userId", userId)，name就是userId*/
        int userId = jwt.getClaim("userId").asInt();
        return userId;
    }


    /**验证token，verify（)是为了校验签名是否被篡改*/
        /**
         *
         * @param token
         */
    public void verifierToken(String token) {
        //创建算法对象
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm).build();//构造验证对象
        /**传入参数token，创建算法对象，验证*/
        verifier.verify(token);//验证
    }
}